/*
 * This file is part of Shopping Lists Organizer software
 *
 * Copyright (C) 2011 Denis Kvita <dkvita@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#include <QtGui>
#include <QtSql>

#include "expensesmodel.h"

expensesModel::expensesModel(QObject *parent) :
	QAbstractTableModel(parent),cc()
{
	rcnt= 0;
}

int expensesModel::rowCount(const QModelIndex &parent) const
{
	return cc.count();
}

int expensesModel::columnCount(const QModelIndex &parent) const
{
	return fieldNames.count();
}

QVariant expensesModel::data(const QModelIndex &index, int role) const
{
	if(role == Qt::DisplayRole || role == Qt::EditRole){
		if(index.column()==0 && role == Qt::DisplayRole && mode == expensesModel::Date){
			switch(dateGroup){
			case expensesModel::Month:
			return QLocale::system().monthName(cc.value(index.row()).value(index.column()).toInt());
			case expensesModel::DayOfWeek:
			return QLocale::system().dayName(cc.value(index.row()).value(index.column()).toInt()==0
											 ?7:cc.value(index.row()).value(index.column()).toInt());
			case expensesModel::Year:;
			case expensesModel::DayOfMonth:;
			}
		}

		if(role == Qt::DisplayRole && (index.column() == 2 || index.column() == 3)){
			double n= cc.value(index.row()).value(index.column()).toDouble();
			int r= (int)(n*1000);
			int rm= r%10;
			r= r/10;
			n= r;
			if(rm >= 5) n= n/100+0.01;
			else n= n/100;
			return QString::number(n,'f',2);
		}

		if(index.column()==0 && role == Qt::EditRole && mode == expensesModel::Date){
			if(dateGroup == expensesModel::DayOfWeek)
				return cc.value(index.row()).value(index.column()).toInt()==0
						?(QLocale::system().country() == QLocale::RussianFederation
						  || QLocale::system().country() == QLocale::Ukraine ? 7: 0)
					   :cc.value(index.row()).value(index.column()).toInt();
		}
		return cc.value(index.row()).value(index.column());
	}
	if( index.column() >0 && role == Qt::BackgroundRole ) return QBrush(QColor(255,255,0,128));
	return QVariant();
}

QVariant expensesModel::headerData(int section, Qt::Orientation orientation, int role) const
{
	if(orientation == Qt::Horizontal){
		if(role == Qt::DisplayRole){
			if(fieldNames.count()< section) return QAbstractTableModel::headerData(section, orientation, role);
			switch(section){
			case 0: return fieldNames.value(section).second;
			break;
			case 1: return fieldNames.value(section).second;
			break;
			case 2: return fieldNames.value(section).second;
			break;
			case 3: return fieldNames.value(section).second;
			break;
			default: return QAbstractTableModel::headerData(section, orientation, role);
			}
		}
	}
	return QAbstractTableModel::headerData(section, orientation, role);
}


Qt::ItemFlags expensesModel::flags(const QModelIndex & index) const
{
	return Qt::ItemIsEnabled;
}

bool expensesModel::insertRows(int row, int count, const QModelIndex & parent)
{
	if(count<=0) return false;
	beginInsertRows(parent, row, row+count-1);
	endInsertRows();
	return true;
}

bool expensesModel::removeRows(int row, int count, const QModelIndex & parent)
{
	if(count<=0) return false;
	beginRemoveRows(parent, row, row+count-1);
	endRemoveRows();
	return true;
}

void expensesModel::clear()
{
	beginResetModel();
	removeRows(0,rowCount());
	cc.clear();
	endResetModel();
}

void expensesModel::updateData()
{
	cc.clear();
	beginResetModel();
	removeRows(0,rowCount());

	fieldNames.clear();
	groupBy.clear();
	QPair<QString,QString> dateG;
	switch(mode){
	case expensesModel::Date:
		switch(dateGroup){
		case expensesModel::Year:
			dateG= qMakePair(QString("strftime('%Y',pDate) as year"),tr("year"));
			groupBy= "strftime('%Y',pDate)";
		break;
		case expensesModel::Month:
			dateG= qMakePair(QString("strftime('%m',pDate) as month"),tr("month"));
			groupBy= "strftime('%m',pDate)";
		break;
		case expensesModel::DayOfMonth:
			dateG= qMakePair(QString("strftime('%d',pDate) as day"),tr("day"));
			groupBy= "strftime('%d',pDate)";
		break;
		case expensesModel::DayOfWeek:
			dateG= qMakePair(QString("strftime('%w',pDate) as day"),tr("day"));
			groupBy= "strftime('%w',pDate)";
		break;
		}

		fieldNames<<dateG
				 <<qMakePair(QString("count(*) as cnt"),tr("purchases"))
				<<qMakePair(QString("sum(pPrcP*pCntP) as planned"),tr("planned cost"))
			   <<qMakePair(QString("sum(pPrcB*pCntB) as cost"),tr("cost"));
	break;
	case expensesModel::Shop:
		fieldNames<<qMakePair(QString("(SELECT sTitle FROM shop WHERE oid=pShop) as shop"),tr("shop"))
				 <<qMakePair(QString("count(*) as cnt"),tr("purchases"))
				<<qMakePair(QString("sum(pPrcP*pCntP) as planned"),tr("planned cost"))
			   <<qMakePair(QString("sum(pPrcB*pCntB) as cost"),tr("cost"));
		groupBy= "pShop";
	break;
	case expensesModel::Category:
		fieldNames<<qMakePair(QString("pCat"),tr("category"))
				 <<qMakePair(QString("count(*) as cnt"),tr("purchases"))
				<<qMakePair(QString("sum(pPrcP*pCntP) as planned"),tr("planned cost"))
			   <<qMakePair(QString("sum(pPrcB*pCntB) as cost"),tr("cost"));
		groupBy= "pCat";
	break;
	case expensesModel::Purchase:
		fieldNames<<qMakePair(QString("pTitle"),tr("purchase title"))
				 <<qMakePair(QString("count(*) as cnt"),tr("purchases"))
				<<qMakePair(QString("sum(pPrcP*pCntP) as planned"),tr("planned cost"))
			   <<qMakePair(QString("sum(pPrcB*pCntB) as cost"),tr("cost"));
		groupBy= "pTitle";
	break;
	}

	// get data from DB
	QSqlDatabase dbc= QSqlDatabase::database("CN");
	QSqlQuery q(dbc);
	q.prepare("SELECT * FROM (SELECT "
			  +fieldNames.value(0).first
			  +","+fieldNames.value(1).first
			  +","+fieldNames.value(2).first
			  +","+fieldNames.value(3).first
			  +" FROM purchase WHERE pDate>=:DB AND pDate<=:DE "
			  +" GROUP BY "+groupBy+" ORDER BY "+groupBy+" ASC )");
	q.bindValue(":DB", beginDate.toString("yyyy-MM-dd"));
	q.bindValue(":DE", endDate.toString("yyyy-MM-dd"));
	q.exec();
	while(q.next()) cc.append(QSqlRecord(q.record()));

	insertRows(0,rowCount());
	endResetModel();
}

void expensesModel::setPeriod(QDate begin, QDate end)
{
	beginDate= begin;
	endDate= end;
}

void expensesModel::setMode(expensesModel::GroupingMode grouping)
{
	mode= grouping;
}

void expensesModel::setDateMode(expensesModel::DateGrouping grouping)
{
	dateGroup= grouping;
}
